﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Metoso_Simplex_Cm
{
    public partial class Form1 : Form
    {
        public String[][] data = {};
        String [,] arreglo;
        String [,] arreglo_temporal;
        String [,] arreglo_transpuesto;
        float [] Vector_solucion;
        float [] Vector_2_Auxiliar;
        float [] indice;
        float [] indice1;
        float pivote,coef_pivotal,temp=0,valor;
        int variable=0,restricciones=0,indiceY=0,indiceX;
        int subY,subY1,subX,subX1,holguras1=0,artificiales1=0;
        String tipo="",M="20000";
        private bool multiple=false,Artificial=false,Solucion_infinita=false,usoDual=false;
        public Form1()
        {
            InitializeComponent();
            
        }

        private void btnCrear_Click(System.Object sender, System.EventArgs e) {
        try{
            variable = Convert.ToInt16(txtVariables.Text);
            restricciones = Convert.ToInt16(txtRestricc.Text);
 
        }catch(Exception ex){
            MessageBox.Show("Digite números", "Error");
            txtVariables.Text = "";
            txtRestricc.Text = "";
 
        }
        if( variable == 1 & restricciones == 1 ){
 
            MessageBox.Show("Debe ingresar almenos 2 restricciones", "Error Casual");
            nuevo();
        }else{
 
            GenerarTitulos(variable);
 
        }
    }  
 
    private void btnIngresar_Click(System.Object sender, System.EventArgs e) {
        string valor1 = null;
        string texto = null;
 
        try{
            Verificar_y_Dimensionar_Primal();
            texto = tipo;
            valor1 = "";
            for(int y= 0; y< (variable + holguras1 + artificiales1); y++){
 
                Vector_solucion[y] = 0;
                Vector_2_Auxiliar[y] = 0;
 
            }
 
            try{
                for(int i= 1; i<= variable; i++){
 
                    valor1 = InputBox("Ingrese X" + i);
                    //Vector solucion de la funcion objetivo
                    Vector_solucion[i - 1] = Convert.ToDouble(valor1);
                    Vector_2_Auxiliar[i - 1] = Vector_solucion[i - 1];
                    texto = texto + (" +  " + valor1 + "X" + i);
 
                }
                setMultiple(false);
                lblEtiqueta.Text = texto;
                btnCalcularPrimal.Enabled = true;
 
            }catch(Exception ex){
                MessageBox.Show("Error digite bien!");
 
 
            }
            if( Artificial ){
 
                for(int y= (holguras1 + variable); y< (variable + holguras1 + artificiales1); y++){
                    Vector_solucion[y] = Convert.ToDouble(M); //Si es dual agregar los Ms
                    Vector_2_Auxiliar[y] = Vector_solucion[y];
                }
 
            }
            for(int y= 0; y< (variable + holguras1 + artificiales1); y++){
 
                Console.WriteLine(" Vector " + Vector_solucion[y]);
 
            }
 
        }catch(Exception ex){
            MessageBox.Show("Tipee en tabla", "Error de ingreso");
 
        }
    }  
 
    private void Rmax_CheckedChanged(System.Object sender, System.EventArgs e) {
        tipo = "Max";
        btnIngresar.Enabled = true;
    }  
 
    private void Rmin_CheckedChanged(System.Object sender, System.EventArgs e) {
        tipo = "Min";
        btnIngresar.Enabled = true;
    }  
 
    private void btnCalcularPrimal_Click(System.Object sender, System.EventArgs e) {
        setMultiple(false);
        LlenarDatosTabla();
        try{
            //LlenarDatosTabla()
        }catch(Exception ex){
            MessageBox.Show("Llene los datos de la tabla", "Error de Tabla");
 
        }
        if( Solucion_infinita ){
 
            MessageBox.Show("Soluciones Infinitas");
        }
        if( isMultiple() ){
            MessageBox.Show("Es degenarada.. Se mostrara el 1° Tablero");
        }
        Resultado_Primal oFrm = new Resultado_Primal(arreglo, variable, restricciones, tipo, holguras1, artificiales1);
        oFrm.Show();
        btnCalcularDual.Enabled = true;
        btnCalcularPrimal.Enabled = false;
    }  
    private void LlenarDatosTabla() {
        if( ValidarCampos() ){
 
            MessageBox.Show("Debe existir <= , >= o =", "Error de usuario");
 
        }
        Asignar_Primal();
        //System.out.println(holguras1 & " otra es " & artificiales1);
        Trabajar_Simplex(arreglo, variable, restricciones);
        Tablero_Iterativo();
 
    }  
    public void Asignar_Primal() {
        int contador = 3 + variable;
        int contador2 = 3 + variable + holguras1;
        for(int i= 0; i< restricciones; i++){
            if( Tabla(variable, i).Value.Equals(">=") ){
                Datos_menos_Holgura_mas_Artificial(i, variable, contador, contador2);
                contador = contador + 1;
                contador2 += 1;
 
            }else if( Tabla(variable, i).Value.Equals("<=") ){
                Datos_mas_Holgura(i, variable, contador);
                contador = contador + 1;
 
            }
        }
        Console.WriteLine(" Tablero inicial ");
        for(int u= 0; u< (restricciones); u++){
 
            for(int y= 0; y< (3 + variable + holguras1 + artificiales1); y++){
 
                Console.Write(arreglo[u, y] + " ");
 
            }
            Console.WriteLine(" ");
        }
    }  
    public void Datos_menos_Holgura_mas_Artificial(object i, object variable, object contador, object contador2) {
        for(int j= 3; j< (variable + 3); j++){
            arreglo[i, j] = Tabla(j - 3, i).Value.ToString();
        }
        arreglo[i, contador] = "-1";
        arreglo[i, contador2] = "1";
        arreglo[i, 2] = Tabla(variable + 1, i).Value.ToString();
        arreglo[i, 1] = "L" + i;
        arreglo[i, 0] = M;
    }  
    public void Datos_mas_Holgura(object i, object variable, object contador) {
        for(int j= 3; j< (variable + 3); j++){
            arreglo[i, j] = Tabla(j - 3, i).Value.ToString();
        }
        arreglo[i, contador] = "1";
        arreglo[i, 2] = Tabla(variable + 1, i).Value.ToString();
        arreglo[i, 1] = "X" + (i + variable + 1);
        arreglo[i, 0] = "0";
    }  
    private void Tablero_Iterativo() {
 
 
    }  
 
    private void Trabajar_Simplex(string( arreglo_interno, object ), int columna, int filas) {
        Llenarzj_cj(arreglo_interno, columna, filas);
        indiceY = Procesar_IndiceY(indice, arreglo_interno);
        Console.WriteLine("Indice Y " + indiceY.ToString());
        valor = Convert.ToDouble(arreglo_interno[filas, indiceY]);
        Console.WriteLine(" Menor valor " + valor.ToString());
        while( valor < 0){
            ///////////////// Inicia Obtener pivote,indiceX,y coef pivotal
            for(int z= 0; z< filas; z++){
                double a = 0;
                indice1[z] = Convert.ToDouble(arreglo_interno[z, 2]) / Convert.ToDouble(arreglo_interno[z, indiceY]);
                a = indice1[z];
                if( Double.IsInfinity(a) ){
                    indice1[z] = 1000000000;
                }
                //Console.WriteLine(indice1(z).ToString)
            }
            indiceX = Procesar_IndiceX(indice1, 1);
            Console.WriteLine("indice X " + indiceX.ToString());
            pivote = Convert.ToDouble(arreglo_interno[indiceX, indiceY]);
            Console.WriteLine("pivote " + pivote.ToString());
            coef_pivotal = Convert.ToDouble(arreglo_interno[indiceX, 2]) / pivote;
            Console.WriteLine("coef pivotal" + coef_pivotal.ToString());
            if( coef_pivotal <= 0 ){
                Solucion_infinita = true;
                break;
            }
            ////////////////// Finaliza Obtener pivote,indiceX,y coef pivotal
 
            ////////////////////Inicia Rellenar nueva fila pivote
            arreglo_temporal[indiceX, 0] = Vector_solucion[indiceY - 3].ToString();
            Console.WriteLine(" in 0 " + arreglo_temporal[indiceX, 0]);
            arreglo_temporal[indiceX, 1] = "X" + (indiceY - 2);
            Console.WriteLine(" in 1 " + arreglo_temporal[indiceX, 1]);
            arreglo_temporal[indiceX, 2] = coef_pivotal.ToString();
            Console.WriteLine(" in 2 " + arreglo_temporal[indiceX, 2]);
            for(int h= 3; h< (3 + columna + holguras1 + artificiales1); h++)
            {
                arreglo_temporal[indiceX, h] = (Convert.ToDouble(arreglo_interno[indiceX, h]) / pivote).ToString();
                Console.WriteLine("nueva fila pivote " + arreglo_temporal[indiceX, h]);
            }
            /////////////////// Finaliza Rellenar nueva fila pivote
 
            for(int m= 0; m< filas; m++){
                if( m != indiceX ){
                    arreglo_temporal[m, 0] = arreglo_interno[m, 0]; //Primeros xk,ck
                    Console.WriteLine(" Xs ant " + arreglo_temporal[indiceX, 0]);
                    arreglo_temporal[m, 1] = arreglo_interno[m, 1];
                    Console.WriteLine(" Xs ant " + arreglo_temporal[indiceX, 1]);
                    arreglo_temporal[m, 2] = (Convert.ToDouble(arreglo_interno[m, 2]) - Convert.ToDouble(arreglo_interno[m, indiceY]) * coef_pivotal).ToString();
                    Console.WriteLine(" Nuevo Bi " + arreglo_temporal[indiceX, 2]);
                    double semipivote = Convert.ToDouble(arreglo_interno[m, indiceY]);
                    for(int n= 3; n< (3 + columna + holguras1 + artificiales1); n++){
 
                        arreglo_temporal[m, n] = (Convert.ToDouble(arreglo_interno[m, n]) - semipivote * Convert.ToDouble(arreglo_temporal[indiceX, n])).ToString();
                        Console.WriteLine("Nueva fila " + arreglo_temporal[m, n]);
                    }
 
                }
            }
            Llenarzj_cj(arreglo_temporal, columna, filas);
            indiceY = Procesar_IndiceY(indice, arreglo_temporal);
            valor = Convert.ToDouble(arreglo_temporal[filas, indiceY]);
            Console.WriteLine(" Menor valor " + valor.ToString());
            arreglo_interno = arreglo_temporal;
 
        }
        arreglo = arreglo_interno;
    }  
    public int Procesar_IndiceX(double() indice11, int i) {
        int valors = 0;
        subX = Obtener_Indice(indice11, i);
        subX1 = Obtener_Indice1(indice11, i);
        if( subX == subX1 ){
            valors = subX;
        }else{
            valors = subX;
            setMultiple(true);
        }
        return valors;
    }  
 
    public bool BuscarXs(int subh, string( arreglo) {
        bool resultado = false;
        int numero = subh + 1;
        for(int k= 0; k< restricciones; k++){
            if( arreglo[k, 1] == "X" + numero.ToString() ){
                resultado = true;
            }
        }
        return resultado;
    }  
    public int Procesar_IndiceY(double() indicep, string( arreglo_interno) {
        int valors = 0;
        subY = Obtener_Indice(indicep, -1);
        subY1 = Obtener_Indice1(indicep, -1);
        if( subY == subY1 ){
            valors = subY + 3;
        }else if( BuscarXs(subY1, arreglo) == false ){
 
            valors = subY + 3;
 
        }else if( BuscarXs(subY, arreglo) == false ){
 
            valors = subY1 + 3;
        }
        return valors;
    }  
    public int Obtener_Indice(double() indi, int p) {
        if( p == 0 ){
            for(int i= 0; i< indi.Length; i++){
                if( indi[i] < 0 ){
                    indi[i] = 1999999999;
                }
            }
        }
        int b = 0;
        for(int i= 0; i< indi.Length; i++){
            if( indi[i] < indi[b] ){
                b = i;
            }
        }
        return b;
    }  
    public int Obtener_Indice1(double() indi, int p) {
        if( p == 0 ){
            for(int i= 0; i< indi.Length; i++){
                if( indi[i] < 0 ){
                    indi[i] = 1999999999;
                }
            }
        }
        int b = 0;
        int b2 = 0;
        for(int i= 0; i< indi.Length; i++){
            if( indi[i] < indi[b] ){
                b = i;
                b2 = b;
            }
            if( indi[i] == indi[b2] ){
                b2 = i;
            }
        }
        return b2;
    }  
    public void Llenarzj_cj(object arreglo1, object columna, object filas) {
        for(int a= 3; a< (3 + columna + holguras1 + artificiales1); a++){
            temp = 0;
            for(int k= 0; k< filas; k++){
 
                temp = temp + Convert.ToDouble(arreglo1[k, 0]) * Convert.ToDouble(arreglo1[k, a]);
            }
            if( Rmax.Checked & usoDual ){
                temp = Vector_solucion[a - 3] - temp;
            }else if( Rmin.Checked & usoDual ){
                temp = temp - Vector_solucion[a - 3];
            }else if( Rmax.Checked ){
                temp = temp - Vector_solucion[a - 3];
            }else if( Rmin.Checked ){
                temp = Vector_solucion[a - 3] - temp;
            }
            Console.WriteLine(" Zj-Cj " + temp.ToString());
            indice[a - 3] = temp;
            arreglo1[filas, a] = temp.ToString();
        }
    }  
 
    private bool ValidarCampos() {
        bool valido = false;
        for(int i= 0; i< restricciones; i++){
            if( Tabla(variable, i).Value.Equals(">=") || Tabla(variable, i).Value.Equals("<=") || Tabla(variable, i).Value.Equals("=") ){
                valido = false;
            }else{
                valido = true;
            }
        }
        return valido;
    }  
 
    private void btnCalcularDual_Click(System.Object sender, System.EventArgs e) {
        if( Rmin.Checked ){
            MessageBox.Show("No programado para minimizacion", "Casualidad");
        }else{
            usoDual = true;
            Verificar_y_Dimensionar_Dual();
            Asignar_Dual();
            Trabajar_Simplex(arreglo_transpuesto, restricciones, variable);
        }
        if( Solucion_infinita ){
            MessageBox.Show("Soluciones Infinitas", "Casualidad");
        }
        Resultado_Dual oFrm = new Resultado_Dual(arreglo, variable, tipo, restricciones, artificiales1, holguras1);
        oFrm.Show();
        btnCalcularDual.Enabled = false;
        btnIngresar.Enabled = false;
    }  
    public void Verificar_y_Dimensionar_Dual() {
        int holguras = 0;
        int artificiales = 0;
        for(int i= 0; i< variable; i++){
            holguras += 1; //Validamos restricciones
            artificiales += 1;
            Artificial = true;
        }
 
        int nuevoF1 = 3 + holguras + artificiales + restricciones;
        int nuevoF2 = variable + 1;
        indice = new double[(holguras + artificiales + restricciones) - 1];
        indice1 = new double[(variable )];
        arreglo_transpuesto = new string[nuevoF2, nuevoF1 - 1];
        arreglo_temporal = new string[nuevoF2, nuevoF1 - 1];
        Vector_solucion = new double[(nuevoF1 - 3 )];
        Llenar0s((holguras + artificiales), restricciones, variable, arreglo_transpuesto);
        holguras1 = holguras;
        artificiales1 = artificiales;
 
    }  
    public void Asignar_Dual() {
        //Dualizar es con minimizacion
        int contador = 3 + restricciones;
        int contador2 = 3 + restricciones + holguras1;
        for(int i= 0; i< variable; i++){
            Datos_menos_Holgura_mas_ArtificialT(i, restricciones, contador, contador2); //Validamos restricciones
            contador = contador + 1;
            contador2 += 1;
 
        }
        //asignar nuevo vector solucion
        for(int a= 0; a< restricciones; a++){
            //Esto transfiere los valores al nuevo vector solucion
            Vector_solucion[a] = Convert.ToDouble(Tabla(variable + 1, a).Value);
        }
        for(int y= (holguras1 + restricciones); y< (restricciones + holguras1 + artificiales1); y++){
            Vector_solucion[y] = Convert.ToDouble(M);
        }
 
 
    }  
    public void Datos_menos_Holgura_mas_ArtificialT(int i, int columna, int contador, int contador2) {
        for(int j= 3; j< (columna + 3); j++){
            arreglo_transpuesto[i, j] = Tabla(i, (j - 3)).Value.ToString();
        }
        arreglo_transpuesto[i, 2] = Vector_2_Auxiliar[i];
        arreglo_transpuesto[i, 1] = "L" + i;
        arreglo_transpuesto[i, 0] = M;
        arreglo_transpuesto[i, contador] = "-1";
        arreglo_transpuesto[i, contador2] = "1";
    }  
    private void GenerarTitulos(int variable) {
        Tabla.ColumnCount = variable + 2;
        Tabla.RowCount = restricciones;
        for(int i= 0; i< variable; i++){
 
            Tabla.Columns[i].Name = "X" + Convert.ToString(i + 1);
 
        }
        Tabla.Columns[variable].Name = "Signo";
        Tabla.Columns[variable + 1].Name = "Valor";
        Tabla.ColumnHeadersVisible = true;
 
    }  
 
    private void Verificar_y_Dimensionar_Primal() {
        int holguras = 0;
        int artificiales = 0;
        for(int i= 0; i< restricciones; i++){
            if( Tabla(variable, i).Value.Equals(">=") ){
 
                holguras += 1; //Validamos restricciones
                artificiales += 1;
                Artificial = true;
            }else if( Tabla(variable, i).Value.Equals("<=") ){
 
                holguras += 1;
            }
        }
 
        int nuevoF1 = 3 + variable + holguras + artificiales;
        int nuevoF2 = restricciones + 1;
        arreglo = new string[nuevoF2 - 1, nuevoF1 - 1];
        arreglo_temporal = new string[nuevoF2 - 1, nuevoF1 - 1];
        Vector_solucion = new double[(nuevoF1 - 3 )];
        Vector_2_Auxiliar = new double[(nuevoF1 - 3 )];
        indice = new double[(variable + holguras + artificiales) - 1];
        indice1 = new double[(restricciones )];
        Llenar0s((holguras + artificiales), variable, restricciones, arreglo);
        holguras1 = holguras;
        artificiales1 = artificiales;
 
    }  
    private void Llenar0s(int valores, int columna, int filas, string( arreglo) {
        for(int i= 0; i< filas; i++){
            for(int h= (columna + 3); h< (columna + valores + 3); h++){
 
                arreglo[i, h] = "0"; //Rellenando con 0's
            }
        }
 
    }  
 
    private void setMultiple(bool p) {
        multiple = p;
 
    }  
    public object isMultiple() {
        return multiple;
    }  
 
    private void nuevoToolStripMenuItem_Click(System.Object sender, System.EventArgs e) {
        nuevo();
    }  
 
    private void salirToolStripMenuItem_Click(System.Object sender, System.EventArgs e) {
        End;
    }  
    public void nuevo() {
        txtRestricc.Text = "";
        txtVariables.Text = "";
        btnCalcularPrimal.Enabled = false;
        btnIngresar.Enabled = false;
        btnCrear.Enabled = true;
    }  
 
    private void AcercaDEToolStripMenuItem_Click(System.Object sender, System.EventArgs e) {
        AcercaDE.Show();
    }  
    }
}
